package com.thunisoft.incremental.task;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Date;

import org.postgresql.copy.CopyManager;
import org.postgresql.core.BaseConnection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.thunisoft.incremental.common.model.Datasource;
import com.thunisoft.incremental.common.model.Task;
import com.thunisoft.incremental.common.model.TaskStatus;
import com.thunisoft.incremental.dao.DatasourceMapper;

import lombok.extern.slf4j.Slf4j;

/**
 * Execute
 *
 * @author Zhang Xin
 * @version v1.0
 * @since 2020/3/27 11:33
 */
@Slf4j
@Component
public class Execute {

    @Autowired
    private DatasourceMapper datasourceMapper;

    public Connection init(String id, boolean autoCommit){
        Datasource datasource = datasourceMapper.selectByPrimaryKey(id);
        Connection conn = null;
        try {
            Class.forName("org.postgresql.Driver");
            StringBuilder jdbcUrl = new StringBuilder();
            jdbcUrl.append("jdbc:postgresql://");
            jdbcUrl.append(datasource.getIp());
            jdbcUrl.append(":").append(datasource.getPort());
            jdbcUrl.append("/").append(datasource.getDatabase());
            jdbcUrl.append("?charset=utf-8");
            conn = DriverManager.getConnection(jdbcUrl.toString()
                    , datasource.getUsername(), datasource.getPassword());
            conn.setAutoCommit(autoCommit);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return conn;
    }

    public void manage(TaskStatus status, Task task) {
        status.setStartTime(new Date());
        log.info("开始执行导出: 【{}】",status.getDataPath());
        copyToFile(init(task.getDatasourceFrom(),true), status.getDataPath(), createSql(task.getViewname()));
        log.info("导出: 【{}】",status.getDataPath());
        log.info("开始执行导入: 【{}】",status.getDataPath());
        copyFromFile(init(task.getDatasourceTo(),true),status.getDataPath(),task.getTablename());
        log.info("导入：【{}】",task.getTablename());
        status.setEntime(new Date());
    }

    public String createSql(String table){
        return String.format("(select * from %s)",table);
    }

    public void copyFromFile(Connection connection, String filePath, String tableName) {

        FileInputStream fileInputStream = null;

        try {
            CopyManager copyManager = new CopyManager((BaseConnection)connection);
            fileInputStream = new FileInputStream(filePath);
            copyManager.copyIn("COPY " + tableName + " FROM STDIN", fileInputStream);
            connection.close();
        } catch (SQLException | IOException e) {
            throw new RuntimeException(e.getMessage(),e);
        } finally {
            if (fileInputStream != null) {
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    log.error(e.getMessage(), e);
                }
            }
        }
    }

    public void copyToFile(Connection connection, String filePath, String tableOrQuery){

        FileOutputStream fileOutputStream = null;

        try {
            CopyManager copyManager = new CopyManager((BaseConnection)connection);
            fileOutputStream = new FileOutputStream(filePath);
            copyManager.copyOut("COPY " + tableOrQuery + " TO STDOUT", fileOutputStream);
            connection.close();
        } catch (SQLException |IOException e) {
            throw new RuntimeException(e.getMessage(),e);
        } finally {
            if (fileOutputStream != null) {
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    log.error(e.getMessage(), e);
                }
            }
        }
    }
}